﻿#region Copyright & License
//
// Project: Quark Framework
// Project site: http://quark.codeplex.com
// See the copyright statement on the project site for more details.
//
// Licensed to the Apache Software Foundation (ASF) under one or more 
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership. 
// The ASF licenses this file to you under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with 
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Quark.Profiler.Framework
{
    /// <summary>
    /// 数组列表工具类
    /// </summary>
    public static class ProfilingArrayUtil
    {
        /// <summary>
        /// 将指定数组转换为一个动态列表
        /// </summary>
        /// <typeparam name="T">数组元素类型</typeparam>
        /// <param name="array">源数组，如果为空值则会自动返回一个零长度的动态列表集合</param>
        /// <returns>包含该数组的动态列表</returns>
        public static List<T> ConvertToList<T>(T[] array) where T : class
        {
            List<T> list;

            if ((array == null) || (array.Length == 0)) list = new List<T>();
            else list = new List<T>(array);

            return list;
        }

        /// <summary>
        /// 向指定数组末尾添加一个元素，如果元素已包含于数组中，则直接返回不会重复添加
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="array">数组</param>
        /// <param name="element">要添加到末尾的元素实例</param>
        /// <returns>返回包含了添加元素的新数组，如果元素已包含于数组中，则直接返回源数组</returns>
        /// <exception cref="ArgumentNullException"><paramref name="element"/>参数为空值</exception>
        public static T[] AddElement<T>(T[] array, T element) where T : class
        {
            if (element == null) throw new ArgumentNullException("element");
            if (array.Contains<T>(element)) return array;

            List<T> list = ConvertToList<T>(array);
            list.Add(element);

            return list.ToArray();
        }

        /// <summary>
        /// 向指定数组索引位置添加一个元素，如果元素已包含于数组中，则直接返回
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="array">数组</param>
        /// <param name="element">要添加到末尾的元素实例</param>
        /// <param name="targetIndex">目标索引位置，必须大于等于0或小于等于数组总长度</param>
        /// <returns>返回包含了添加元素的新数组，如果元素已包含于数组中，则直接返回源数组</returns>
        /// <exception cref="ArgumentNullException"><paramref name="element"/>参数为空值</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="targetIndex"/>超出边界</exception>
        public static T[] InsertElement<T>(T[] array, T element, int targetIndex) where T : class
        {
            if (element == null) throw new ArgumentNullException("element");
            if (array.Contains<T>(element)) return array;
            if ((targetIndex < 0) || (targetIndex > (array == null ? 0 : array.Length))) throw new ArgumentOutOfRangeException("targetIndex");

            List<T> list = ConvertToList<T>(array);
            list.Insert(targetIndex, element);

            return list.ToArray();
        }

        /// <summary>
        /// 从数组中删除指定元素，如果元素未包含于数组中，则直接返回
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="array">数组</param>
        /// <param name="element">要添加到末尾的元素实例</param>
        /// <returns>返回包含了添加元素的新数组，如果元素未包含于数组中，则直接返回源数组</returns>
        /// <exception cref="ArgumentNullException"><paramref name="element"/>参数为空值</exception>
        public static T[] RemoveElement<T>(T[] array, T element) where T : class
        {
            if (element == null) throw new ArgumentNullException("element");
            if (!array.Contains<T>(element)) return array;

            List<T> list = ConvertToList<T>(array);
            list.Remove(element);

            return list.ToArray();
        }

        /// <summary>
        /// 将数组中的指定元素向上移动一个索引位置，如果元素未包含于数组中，则直接返回
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="array">数组</param>
        /// <param name="element">要移动的元素实例</param>
        /// <returns>返回移动后的新数组，如果元素未包含于数组中，则直接返回源数组</returns>
        /// <exception cref="ArgumentNullException"><paramref name="element"/>参数为空值</exception>
        public static T[] MoveElementUp<T>(T[] array, T element) where T : class
        {
            if (element == null) throw new ArgumentNullException("element");
            if (!array.Contains<T>(element)) return array;

            List<T> list = ConvertToList<T>(array);
            int currentIndex = list.IndexOf(element);
            if (currentIndex > 0)
            {
                list.RemoveAt(currentIndex);
                list.Insert(currentIndex - 1, element);
            }

            return list.ToArray();
        }

        /// <summary>
        /// 将数组中的指定元素向下移动一个索引位置，如果元素未包含于数组中，则直接返回
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="array">数组</param>
        /// <param name="element">要移动的元素实例</param>
        /// <returns>返回移动后的新数组，如果元素未包含于数组中，则直接返回源数组</returns>
        public static T[] MoveElementDown<T>(T[] array, T element) where T : class
        {
            if (element == null) throw new ArgumentNullException("element");
            if (!array.Contains<T>(element)) return array;

            List<T> list = ConvertToList<T>(array);
            int currentIndex = list.IndexOf(element);
            if (currentIndex < (list.Count - 1))
            {
                list.RemoveAt(currentIndex);
                list.Insert(currentIndex + 1, element);
            }

            return list.ToArray();
        }
    }
}
